#include "Ogre\ExampleApplication.h"


class Example1 : public ExampleApplication
{
	private:
		Ogre::SceneNode* *mNodes;
		Ogre::Entity* *mEntities;
		size_t mMany;

		void setup_nodes_and_entities(size_t n)  
		{ 
			mMany = n;
			mNodes = new Ogre::SceneNode*[mMany];
			mEntities = new Ogre::Entity*[mMany];
			std::string entity_name_prefix = "MyEntity";
			std::string node_name_prefix = "Node";
			std::stringstream ss;
			for (int i =0; i< mMany; i++) 
			{
				ss.str("");
				ss << entity_name_prefix << i;
				mEntities[i] = mSceneMgr->createEntity(ss.str(),"Sinbad.mesh");
				ss.str("");
				ss << node_name_prefix << i;
				mNodes[i] = mSceneMgr->createSceneNode(ss.str());
			}

			Example1::setup_nodes_and_entities(mSceneMgr, n, mNodes, mEntities);
		}

		// absurd design, just warming up
		static void setup_nodes_and_entities(Ogre::SceneManager *manager, size_t n, Ogre::SceneNode* nodes[], Ogre::Entity* entities[]) 
		{
			for(int i = 0; i < n; i++) {
				if (i == 0) 
				{
					manager->getRootSceneNode()->addChild(nodes[i]);
				}
				else
				{
					nodes[0]->addChild(nodes[i]);
				}
				nodes[i]->attachObject(entities[i]);
			}
		}


		// methods meant to be called in createScene(), just exactly one of these
		void two_simbads() 
		{
		// Two Simbads
			Ogre::SceneNode* node = mSceneMgr->createSceneNode("Node1");
			mSceneMgr->getRootSceneNode()->addChild(node);
			node->setPosition(10,0,0);

			Ogre::Entity* ent = mSceneMgr->createEntity("MyEntity","Sinbad.mesh");
			node-> attachObject(ent);

			Ogre::SceneNode* node2 = mSceneMgr->createSceneNode("Node2");
			node->addChild(node2);
			node2->setPosition(0,10,20);
			Ogre::Entity* ent2 = mSceneMgr->createEntity("MyEntity2","Sinbad.mesh");
			node2->attachObject(ent2);
		}

		void simbad_rotations() {
			setup_nodes_and_entities(4);

			mNodes[0]->setPosition(10,10,0);

			mNodes[1]->setPosition(10,0,0);
			// pitch() rotates around the X-axis (horizontal right)
				// use of radian units for rotation
			mNodes[1]->pitch(Ogre::Radian(Ogre::Math::HALF_PI));

			// translate is relative as it adds to the current node position
			// vs. setPosition with sets an absolute location for the node
			mNodes[2]->translate(20,0,0);
			//yaw() rotates around the Y-axis (vertical up)
				// use of degree units for rotation
			mNodes[2]->yaw(Ogre::Degree(90.0f));
		
			mNodes[3]->setPosition(30,0,0);
			//roll() rotates around the Z-axis (out of the screen)
			mNodes[3]->roll(Ogre::Radian(Ogre::Math::HALF_PI));
		}

		void simbad_scalations() {
			Ogre::Entity* ent = mSceneMgr->createEntity("MyEntity","Sinbad.mesh");
			Ogre::SceneNode* node = mSceneMgr->createSceneNode("Node1");
			node->setPosition(10,10,0);
			mSceneMgr->getRootSceneNode()->addChild(node);
			node->attachObject(ent);

			Ogre::Entity* ent2 = mSceneMgr->createEntity("MyEntity2","Sinbad.mesh");
			Ogre::SceneNode* node2 = node->createChildSceneNode("node2");
			node2->setPosition(10,0,0);
			node2->attachObject(ent2);
			node2->scale(2.0f,2.0f,2.0f);

			Ogre::Entity* ent3 = mSceneMgr->createEntity("MyEntity3","Sinbad.mesh");
			Ogre::SceneNode* node3 = node->createChildSceneNode("node3",Ogre::Vector3(20,0,0));
			node3->scale(0.2f,0.2f,0.2f);
		}

	// methods meant to be called in createScene(), just exactly one of these # END

	public:
	~Example1() 
	{
		// mSceneMgr already deletes the created nodes and entities? 
		delete[] mEntities;
		delete[] mNodes;
	}

	// override
	void createScene()
	{
		simbad_rotations();
	}
};

int main(void) 
{
	Example1 app;
	app.go();
	return 0;
}
